package controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import controller.behavior.Behavior;
import controller.behavior.BulletAI;
import controller.behavior.EasyAI;
import controller.behavior.ZeroHuman;
import model.BulletModel;
import model.Model;
import model.TankModel;
import util.Direction;
import util.MyPosition;
import util.MyRectangle;
import view.BulletView;
import view.ModelView;
import view.TankView;
import view.fragme.MyJFrame;

public class JFrameController {
    private Map<Long, BulletModel> bulletModels;
    private MyJFrame frame;
    private ZeroHuman human;
    private MyThread myThread;
    private List<Behavior> ais;

    public JFrameController(MyJFrame frame) {
        this.frame = frame;
        myThread = new MyThread();
        ais = new ArrayList<>();
        bulletModels = new HashMap<>();

        gameInit();
    }

    public void gameEnd() {
        gameDestroy();
    }

    private void gameDestroy() {
        bulletModels.clear();
        frame = null;
        human = null;
    }

    private void gameInit() {
        myThread.start();
        redBorn();
        blueBorn();
    }

    private void blueBorn() {
        TankModel tankModel = new TankModel(Model.BLUE_CAMP, 0);
        TankView tankView = new TankView(new MyPosition(50, 200, 25, 25), tankModel);
        EasyAI ai = new EasyAI(tankModel, tankView);
        ais.add(ai);
        frame.add(tankView);

        tankModel = new TankModel(Model.BLUE_CAMP, 0);
        tankView = new TankView(new MyPosition(150, 200, 25, 25), tankModel);
        ai = new EasyAI(tankModel, tankView);
        ais.add(ai);
        frame.add(tankView);
    }

    private void redBorn() {
        TankModel tankModel = new TankModel(Model.RED_CAMP, 0);
        TankView tankView = new TankView(new MyPosition(50, 50, 25, 25), tankModel);
        frame.add(tankView);
        human = new ZeroHuman(tankModel, tankView, this);

        frame.addKeyListener(human);
    }

    class MyThread extends Thread {
        public MyThread() {
            setName("My Thread");
        }

        @Override
        public void run() {
            while (true) {
                for (int i = 0; i < ais.size(); i++) {
                    Behavior item = ais.get(i);

                    Direction newDir = item.move(true);
                    item.getView().setDir(newDir);
                    MyPosition newPosition = getNewPosition(item.getModel(), item.getView());
                    // 如果是子弹并且越界了
                    if (item instanceof BulletAI && newPosition == item.getView().getPosition()) {
                        ais.remove(item);
                        frame.remove((BulletView) item.getView());
                    } else
                        item.getView().setPosition(newPosition);

                    // 如果子弹成功呗发射出来了
                    BulletModel bulletModel = item.fire(true);
                    if (bulletModel != null) {
                        BulletView bulletView = new BulletView(item.getView().getPosition(), bulletModel,
                                item.getView().getFace());
                        Behavior bulletAI = new BulletAI(bulletModel, bulletView);
                        ais.add(bulletAI);
                        frame.add(bulletView);
                    }

                    if (item instanceof BulletAI) {
                        // 如果是子弹
                        for (int c = 0; c < ais.size(); c++) {
                            Behavior ai = ais.get(c);
                            if (ai != item && ai instanceof EasyAI &&
                                    new MyRectangle(item.getView().getPosition(), ai.getView().getPosition()).check()
                                    && ai.getModel().getCamp() != item.getModel().getCamp()) {
                                // 不是自身&& 被撞者是坦克 && 双方阵营不同
                                int power = ((BulletModel) item.getModel()).getPower();
                                double blood = power / (double) ai.getModel().getBlood();
                                ((TankView) ai.getView()).changeBlood(blood);
                                if (ai.isLife() == false)
                                    death(ai);
                                beCollision(ai);
                            }
                        }
                    } else if (item instanceof EasyAI) {
                        // 如果是坦克
                        for (int c = 0; c < ais.size(); c++) {
                            Behavior ai = ais.get(c);
                            if (ai != item && ai instanceof EasyAI
                                    && new MyRectangle(ai.getView().getPosition(), item.getView().getPosition())
                                            .check()) {
                                // 如果被撞者是坦克
                                item.stay();
                                beCollision(ai);
                            } else if (ai != item && ai instanceof BulletAI &&
                                    new MyRectangle(ai.getView().getPosition(), item.getView().getPosition()).check() &&
                                    ai.getModel().getCamp() != item.getModel().getCamp()) {
                                // 如果被撞者是子弹
                                int power = ((BulletModel) ai.getModel()).getPower();
                                double blood = power / (double) ai.getModel().getBlood();
                                ((TankView) item.getView()).changeBlood(blood);
                                beCollision(ai);
                            }
                        }
                    }
                }
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public MyPosition getNewPosition(Model model, ModelView modelView) {
        Direction viewDir = modelView.getDir();
        int speed = model.getSpeed();
        MyPosition newPosition = new MyPosition(modelView.getPosition());

        if (viewDir != Direction.STOP) {
            switch (viewDir) {
                case L:
                    newPosition.setX(newPosition.getX() - speed);
                    break;
                case LU:
                    newPosition.setX(newPosition.getX() - speed);
                    newPosition.setY(newPosition.getY() - speed);
                    break;
                case U:
                    newPosition.setY(newPosition.getY() - speed);
                    break;
                case RU:
                    newPosition.setX(newPosition.getX() + speed);
                    newPosition.setY(newPosition.getY() - speed);
                    break;
                case R:
                    newPosition.setX(newPosition.getX() + speed);
                    break;
                case RD:
                    newPosition.setX(newPosition.getX() + speed);
                    newPosition.setY(newPosition.getY() + speed);
                    break;
                case D:
                    newPosition.setY(newPosition.getY() + speed);
                    break;
                case LD:
                    newPosition.setX(newPosition.getX() - speed);
                    newPosition.setY(newPosition.getY() + speed);
                    break;
                case STOP:
                    break;
            }
        }

        if (newPosition.getX() < 0)
            return modelView.getPosition();
        if (newPosition.getY() < 0)
            return modelView.getPosition();
        if ((newPosition.getX() + newPosition.getWidth() + 15) > MyJFrame.GAME_WIDTH)
            return modelView.getPosition();
        if ((newPosition.getY() + newPosition.getHeight() + 40) > MyJFrame.GAME_HEIGHT)
            return modelView.getPosition();

        return newPosition;
    }

    public void beCollision(Behavior ai) {
        if (ai instanceof BulletAI) {
            ais.remove(ai);
            frame.remove((BulletView) ai.getView());
        } else if (ai instanceof EasyAI) {
            ai.getView().stay();
        }
    }

    private void death(Behavior ai) {
        frame.remove((TankView) ai.getView());
        ais.remove(ai);
    }

    // set&get

    public Map<Long, BulletModel> getBulletModels() {
        return bulletModels;
    }

    public MyJFrame getFrame() {
        return frame;
    }

    public List<Behavior> getAis() {
        return ais;
    }

}
